#include <Stepper.h>

#define X  10//具有输出PWM输出能力的角
#define Y  4
#define Z  7
#define x_enable  11//使能控制
#define y_enable  5
#define z_enable  8
#define x_dir  12//方向控制
#define y_dir  6
#define z_dir  9

long int x_steps=0;
long int y_steps=0;
long int z_steps=0;

String comdata = "";  // 用于存储串口接收信息
long int numdata[6] = {0,0,0,0,0,0},  mark = 0; //numdata是分拆之后的数字数组

int i = 0;//存储最新数值变数，我们将使用它来从上到下计数
int steps;//步数

void tone_pwm(int pin,long int frequency,float percent);
void t_move(int pin,long int v,long int steps); //v运动
void xy_move_line(int x_pin,long int x_steps,int y_pin,long int y_steps,long int v); //xy插值直线运动
void dir(int pin,long int steps);

void setup(){  
  for(int i = 4; i < 13; i++) {
    pinMode(i, OUTPUT);
  }
  Serial.begin(9600);
}

void loop(){
  // 使能电机
  digitalWrite(x_enable, HIGH); 
  digitalWrite(y_enable, HIGH); 
  digitalWrite(z_enable, HIGH); 
  // 读取串口信息
  while (Serial.available() > 0) {
    comdata += char(Serial.read());//读入之后将字符串，串接到comdata上面。
    delay(50);//延时一会，让串口缓存准备好下一个数字，不延时会导致数据丢失，
    mark = 1;//标记串口读过数据，如果没有数据的话，直接不执行这个while了。
  }
  
  // 将串口信息comdata转移到数组信息numdata
  if(mark == 1) {
    //如果接收到数据则执行comdata分析操作，否则什么都不做。
    //收到#号命令
    if(comdata[0] == '#') {
      Serial.print("执行调整#命令：\n");
      int j = 0;//不断循环检测串口缓存，一个个读入字符串，
      int flag=1;//用于表示正负号
      for(int i = 0; i < comdata.length() ; i++) {                 
        //以串口读取字符串长度循环，
        //逐个分析comdata[i]字符串的文字，如果碰到文字是分隔符（这里选择逗号分割）则将结果数组位置下移一位   
        if(comdata[i] == '#'){ j=0;numdata[j]=1; }//以#号开始,numdata[0]表示微调距离
        if(comdata[i] == ','||comdata[i] == '#') {
          //即比如11,22,33,55开始的11记到numdata[0];碰到逗号就j等于1了，
          //再转换就转换到numdata[1];再碰到逗号就记到numdata[2];以此类推，直到字符串结束
          numdata[j]=numdata[j]*flag;j++; flag=1;
        }
        else {
          if(comdata[i]=='-') {
            flag=-1;/*Serial.print(flag); Serial.print(comdata[i]-'0');*/
          }
          else
            numdata[j] = numdata[j] * 10 + (comdata[i] - '0');//comdata的字符串已经全部转换到numdata了，清空comdata以便下一次使用，
        }         
      }    
      numdata[j]=numdata[j]*flag;//最后一步退出循环了，所以要加上正负号 
      //循环输出numdata的内容，并执行电机操作
      if(numdata[i]==1) {
        Serial.print("#pin=");//输出基本参数
        Serial.print(numdata[1]);
        Serial.print(",v=");
        Serial.print(numdata[2]);
        Serial.print(",steps=");
        Serial.println(numdata[3]);
        //Serial.println(numdata[4]);
        //Serial.println(numdata[5]);
        // 执行电机操作
        if(numdata[1]==1)     {Serial.println("X");t_move(X,numdata[2],numdata[3],0.5);}
        else if(numdata[1]==2){Serial.println("Y");t_move(Y,numdata[2],numdata[3],0.5);}
        else if(numdata[1]==3){Serial.println("Z");t_move(Z,numdata[2],numdata[3],0.5);}
      }     
    }
    
    //收到*命令
    else if(comdata[0] == '*') {
      Serial.print("执行形状*命令：\n");
      int j = 0;//不断循环检测串口缓存，一个个读入字符串，
      int flag=1;//用于表示正负号
      for(int i = 0; i < comdata.length() ; i++) {                 
        //以串口读取字符串长度循环，
        //逐个分析comdata[i]字符串的文字，如果碰到文字是分隔符（这里选择逗号分割）则将结果数组位置下移一位   
        if(comdata[i] == '*'){ j=0;numdata[j]=1; }//以#号开始,numdata[0]表示微调距离
        if(comdata[i] == ','||comdata[i] == '*') {
          //即比如11,22,33,55开始的11记到numdata[0];碰到逗号就j等于1了，
          //再转换就转换到numdata[1];再碰到逗号就记到numdata[2];以此类推，直到字符串结束
          numdata[j]=numdata[j]*flag;j++; flag=1;
        }
        else {
          if(comdata[i]=='-') {
            flag=-1;/*Serial.print(flag); Serial.print(comdata[i]-'0');*/
          }
          else
            numdata[j] = numdata[j] * 10 + (comdata[i] - '0');//comdata的字符串已经全部转换到numdata了，清空comdata以便下一次使用，
        }         
      }    
      numdata[j]=numdata[j]*flag;//最后一步退出循环了，所以要加上正负号 
      //循环输出numdata的内容，并执行电机操作
      if(numdata[i]==1) {
        Serial.print("*mode=");//输出基本参数
        Serial.print(numdata[1]);
        Serial.print(",v=");
        Serial.print(numdata[2]);
        Serial.print(",steps=");
        Serial.println(numdata[3]);
        Serial.print(",times=");
        Serial.println(numdata[4]);
        //Serial.println(numdata[5]);
        // 执行电机回字形操作
        if(numdata[1]==1) {
          Serial.println("回字形");
          int deltx = numdata[3]/numdata[4]/2;
          int changex = 0;
          int change2x = 0;
          for(int k=0; k<numdata[4]; k++) {
            changex = numdata[3]-2*k*deltx;
            change2x = (-1)*(numdata[3]-(2*k+1)*deltx);
            t_move(X,numdata[2],changex,0.5);
            t_move(Z,numdata[2],changex,0.5);
            t_move(X,numdata[2],change2x,0.5);
            t_move(Z,numdata[2],change2x,0.5);
          }
        }
        // 执行电机操作
        else if(numdata[1]==2) {
          Serial.println("Z字形");
          int deltx = numdata[3]/numdata[5];
          for(int k=0; k<numdata[4]; k++) {
            t_move(Z,numdata[2],numdata[3],0.5);
            t_move(X,numdata[2],deltx,0.5);
            t_move(Z,numdata[2],-numdata[3],0.5);
            t_move(X,numdata[2],deltx,0.5);
          }
        }
        else
          Serial.println("请按操作输入正确指令");
        //if(numdata[1]==1)     {Serial.println("X");t_move(X,numdata[2],numdata[3],0.5);}
        //else if(numdata[1]==2){Serial.println("Y");t_move(Y,numdata[2],numdata[3],0.5);}
        //else if(numdata[1]==3){Serial.println("Z");t_move(Z,numdata[2],numdata[3],0.5);}
      } 
    }
    
    //收到错误命令
    else {
      Serial.print("请重新输入（*或#）:\n");
    }
    
    // 执行重置操作，进入下一个循环
    comdata = String("");//如果不请空的话，本次结果极有可能干扰下一次。 
    for(i=0;i<6;i++) {   
      numdata[i] = 0;
    }
    mark = 0;//输出之后必须将读到数据的mark置0，不置0下次循环就不能使用了。
  }
  delay(20);
}
//-------------------走直线--------------------------
void t_move(int pin,long int v,long int steps,float percent) {
  //v运动
  long int time_move=0;
  int i;
  time_move=1000000/v; //Serial.print(time_move);
  dir(pin,steps);//方向设定
  steps=abs(steps);
  for(i=0;i<steps;i++) {
    tone_pwm(pin,v,percent);
  }
  if(i>=steps) { Serial.println("end1"); } //电机正常结束循环
  else { Serial.println("end0"); } //电机有可能没有跑完步数就提前结束
  }
//-------------------方向--------------------------
void dir(int pin,long int steps) {
  //set the X,Y,Z direction 
  if(steps<0) {
    if(pin==X) { digitalWrite(x_dir,HIGH); }
    else if(pin==Y){ digitalWrite(y_dir,HIGH); }
    else if(pin==Z){ digitalWrite(z_dir,HIGH); }
  }
  else {
    if(pin==X) { digitalWrite(x_dir, LOW); }
    else if(pin==Y){ digitalWrite(y_dir,LOW); }
    else if(pin==Z) { digitalWrite(z_dir,LOW); }
  }
}
//-------------------脉冲--------------------------
void tone_pwm(int pin,long int frequency,float percent) {
  long int t=0;
  t=1000000/ frequency;//将时间转化为微妙
  digitalWrite(pin,HIGH);
  delayMicroseconds( t* percent);
  digitalWrite(pin,LOW);
  delayMicroseconds( t*(1- percent));    
}
